<template>
	<view style="display: flex;justify-content: space-between;flex-direction: column;align-items: center;">
		<view class="" style="width: 500px;">

			<view style="background-color: #fff;border-style: dashed;width: 500px; padding: 10px;">
				<view style="padding: 10px;text-align: center;background-color: aquamarine;">
					参数
				</view>
				<view style="display: flex;line-height: 3em;align-items: center;">
					<view style="width: 100px;">链接地址：</view>
					<input type="text" style="background-color: #eee; flex: 1;" v-model="wsUrl" />
				</view>
				<view style="display: flex;">
					<!-- <textarea type="text" v-model="loginData" /> -->
				</view>
				<view style="width: 100%;display: flex;">
					<view style="width: 100px;">消息体：</view>
					<textarea style="background-color: #eee; flex: 1;" v-model="msg" placeholder="" />
				</view>
			</view>
			<view style="background-color: aliceblue;border-style: dashed;width: 500px; padding: 10px;">
				<view style="padding: 10px;text-align: center;background-color: aquamarine;">
					消息体模板
				</view>
				<button @click="msg=JSON.stringify(loginData);ACT=SENT_BODY">1 登录验证 </button>
				<button @click="msg=JSON.stringify(bindRoom);ACT=SENT_BODY">2 进入房间 </button>
			</view>
			<view style="background-color: aliceblue;border-style: dashed;width: 500px; padding: 10px;">
				<view style="padding: 10px;text-align: center;background-color: aquamarine;">
					操作执行
				</view>
				<view>
					<button @click="connect"> 1 建立链接 </button>
					<button @click="sendMsg(ACT,msg)">2 发送消息 </button>
				</view>
			</view>
			<view style="background-color: aliceblue;border-style: dashed;width: 500px;padding: 10px; ">
				<view style="padding: 10px;text-align: center;background-color: aquamarine;">
					聊天示例
				</view>
				<view>
					<view>1. 建立链接</view>
					<view>2. 消息体模板->登录验证</view>
					<view>3. 发送消息</view>
					<view>到这里就完成了链接鉴权，可以接受到消息了，如果要发送消息，需要使用服务端提供的api接口推送。</view>
				</view>
			</view>
		</view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				bindRoom: {
					"key": "room_bind",
					"token": "3b85a529cc3cb123d9b40d120876e7e1",
					"roomNo": "19"
				},
				loginData: {
					key: "client_bind",
					timestamp: new Date().getTime(),
					data: {
						"token": "3b85a529cc3cb123d9b40d120876e7e1",
						"channel": "web",
						"appVersion": "1.0.0",
						"osVersion": "1.0.1",
						"packageName": "cn.yunque",
						"deviceId": "12345dfdsf343",
						"deviceName": "google",
						"language": "zh-CN"
					}
				},
				msg: '{"token":"3b85a529cc3cb123d9b40d120876e7e1","deviceId":"12345dfdsf343"}',
				token: "xxxx",
				title: 'websocket 链接示例',
				wsUrl: "ws://192.168.1.51:9001/ws",
				isRestCon: false,
				socketTask: null,
				/*
				 *特殊的消息类型，999代表被服务端强制下线
				 */
				ACTION_999: "999",
				DATA_HEADER_LENGTH: 1,
				//参考消息类型目前仅用到0,1,2和999 action={2:通讯消息(推送消息),999:强制下线退出登录,3:未定义消息体(推送消息),4:未定义消息体(回复的消息)}
				MESSAGE: 2,
				// 消息类型4
				REPLY_BODY: 4,
				// 消息类型3 登录鉴权
				SENT_BODY: 3,
				// 心跳接受到 马上回复
				PING: 1,
				// 心跳回复给服务的
				PONG: 0,
				PONG_BODY: "",
				ACT: 0,
			}
		},
		onLoad() {


		},
		methods: {
			//链接并打开
			connect() {
				try {
					if (this.isRestCon || this.socketTask != null) {
						return
					}
					this.isRestCon = true
					this.socketTask = uni.connectSocket({
						url: this.wsUrl,
						// protocols:[],
						success: () => {
							this.isRestCon = false
							console.log("正在建立链接");
						},
						fail: (err) => {
							console.log(err)
							this.isRestCon = false
							//重连
							this.connect();
						},
					});
					//打开链接正常
					this.socketTask.onOpen(async (res) => {
						console.log("打开链接成功");
						// 登录鉴权
						// this.bindAccount()
						//监听接收消息
						this.socketTask.onMessage((res) => {

							this.onMessage(res)
							console.log("接受到消息")
						});
					})
					this.socketTask.onError((err) => {
						console.log(err)
						//重连
						this.connect();
					})
					this.socketTask.onClose(() => {
						this.socketTask = null
						console.log('onClose');
						//重连
						//
						this.connect();
					})
				} catch (e) {
					console.log(e)
					//重连
					//
					this.connect();
				}
			},
			// 綁定账号
			bindAccount() {

				var data = this.loginData

				this.sendMsg(this.SENT_BODY, data)

			},
			//发送消息
			sendMsg(act, obj) {
				console.log(typeof obj)
				const encoder = new TextEncoder();
				var str
				if (typeof obj == 'object') {
					str = JSON.stringify(obj);
				} else {
					str = obj
				}

				const uint8Array = encoder.encode(str);
				var uint8Array2 = new Uint8Array(uint8Array.length + 1);
				uint8Array2[0] = act;
				uint8Array2.set(uint8Array, 1);
				var that = this
				this.socketTask.send({
					data: uint8Array2.buffer,
					async success() {
						console.log('消息发送成功')
					},
					async fail() {
						//重连
						that.connect();
					}
				})
			},

			// 收到的消息
			onMessage(e) {
				this.PONG = 0
				this.PING = 1
				this.MESSAGE = 2
				this.SENT_BODY = 3
				this.REPLY_BODY = 4
				let msg
				let data = new Uint8Array(e.data);
				//第一个值 是消息类型
				let type = data[0];
				const uint8Array = data.slice(1, data.length);
				const arrayBuffer = uint8Array.buffer;
				const textDecoder = new TextDecoder();
				const body = textDecoder.decode(arrayBuffer)
				console.log([type, body])
				switch (type) {
					case
					this.PING:
						this.pong();
						break
					case this.MESSAGE:
						// 消息
						try {
							msg = body;
						} catch (e) {

						}
						break
					case this.REPLY_BODY:
						// 服务端推过来的消息内容
						msg = body;
						if (msg.key === 'client_bind') {
							var
								code = parseInt(msg.code)
							switch (code) {
								case 200:
									console.log('wss握手绑定成功')
									break;
								case 401:
									console.log('wss握手绑定失败')
									break;
								default:
									break;
							}
						}
						break
					default:
						break
				}
			},
			//手动关闭链接
			close() {
				this.socketTask.close({
					success(res) {
						console.log("手动关闭成功")
					},
					fail(err) {}
				})
			},
			pong() {
				this.sendMsg(this.PONG, "PONG")
			}

		}
	}
</script>
<style>

</style>